package com.hxzy.common.aspect;

import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.hxzy.common.annon.Sensitive;
import com.hxzy.common.enums.SensitiveEnum;

import java.io.IOException;
import java.util.Objects;

/**
 * 自定义序列化的json规则 ,
 * JsonSerializer  自定义序列化的操作 用自己规则来实现序列化
 * ContextualSerializer  通过注解显式的声明序列化方式，实现返回的对象进行转译
 */
public class SensitiveSerialize extends JsonSerializer<String> implements ContextualSerializer {

    /**
     * 必须要有默认构造函数
     * 不然会报 Unsatisfied dependency expressed through constructor parameter 0
     */
    public SensitiveSerialize() {
    }

    /**
     * 自定义注解
     */
    private Sensitive   sensitive;

    public SensitiveSerialize(Sensitive   sensitive) {
        this.sensitive = sensitive;
    }

    /**
     * 如何来进行 序列化操作（格式化数据的）
     * @param value
     * @param jsonGenerator
     * @param serializers
     * @throws IOException
     */
    @Override
    public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializers) throws IOException {
        //数据脱敏
        String desValue = desensitized(value, this.sensitive.type());
        jsonGenerator.writeString(desValue);
    }


    /**
     * 数据脱敏后的值
     * @param str
     * @param sensitiveEnum   枚举
     * @return
     */
    public static  String desensitized(CharSequence str, SensitiveEnum  sensitiveEnum) {
        if (StrUtil.isBlank(str)) {
            return StrUtil.EMPTY;
        }
        String newStr = String.valueOf(str);
        switch (sensitiveEnum) {
            case CHINESE_NAME:
                newStr = DesensitizedUtil.chineseName(String.valueOf(str));
                break;
            case ID_CARD:
                newStr = DesensitizedUtil.idCardNum(String.valueOf(str), 1, 2);
                break;
            case FIXED_PHONE:
                newStr = DesensitizedUtil.fixedPhone(String.valueOf(str));
                break;
            case MOBILE_PHONE:
                newStr = DesensitizedUtil.mobilePhone(String.valueOf(str));
                break;
            case ADDRESS:
                newStr = DesensitizedUtil.address(String.valueOf(str), 8);
                break;
            case EMAIL:
                newStr = DesensitizedUtil.email(String.valueOf(str));
                break;
            case PASSWORD:
                newStr = DesensitizedUtil.password(String.valueOf(str));
                break;
            case CAR_LICENSE:
                newStr = DesensitizedUtil.carLicense(String.valueOf(str));
                break;
            case BANK_CARD:
                newStr = DesensitizedUtil.bankCard(String.valueOf(str));
                break;
            case OTHER:
                newStr =StrUtil.hide(String.valueOf(str), 1,str.length()-2);
                break;
            default:
        }
        return newStr;
    }



    /**
     * 获取当前要序列化的列的字段信息
     * @param serializerProvider
     * @param property
     * @return
     * @throws JsonMappingException
     */
    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty property) throws JsonMappingException {

        //字段不null
        if (property != null) {
            // 属性类型是 String类型
            if (Objects.equals(property.getType().getRawClass(), String.class)) {

                //  判断某个字段上面是否有某些注解
                Sensitive sensitive = property.getAnnotation(Sensitive.class);

                // 如果没有，按照jackson规则实现
                if (sensitive == null) {
                    sensitive = property.getContextAnnotation(Sensitive.class);
                }

                if (sensitive != null) {
                    //  按自己的规则实现
                    return new SensitiveSerialize(sensitive);
                }
            }


            // 直接返回值
            return serializerProvider.findValueSerializer(property.getType(), property);
        }

        // 默认的序列化方式来实现
        return serializerProvider.findNullValueSerializer(null);

    }
}
